﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Analyst3D;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using System.Runtime.InteropServices;
using System.Data;
using System.Configuration;
using ESRI.ArcGIS.Geometry;

namespace FRS.EsriExtension
{
    public static class IGeoFeatureLayerExtension
    {
        ///// <summary>
        ///// 获取某个图层中某个字段的唯一值
        ///// </summary>
        ///// <param name="pFeatureLayer">图层</param>
        ///// <param name="fieldName">字段</param>
        ///// <returns>唯一值list</returns>
        //public static List<string> GetUniqueValue(this IFeatureLayer pFeatureLayer, string fieldName)
        //{
        //    try
        //    {
        //        List<string> resultList = new List<string>();

        //        // 使用FeatureClass对象的IDataset接口来获取dataset和workspace的信息
        //        IDataset dataset = pFeatureLayer.FeatureClass as IDataset;
        //        //使用IQueryDef接口的对象来定义和查询属性信息。通过IWorkspace接口的CreateQueryDef()方法创建该对象。
        //        IQueryDef queryDef = (dataset.Workspace as IFeatureWorkspace).CreateQueryDef();
        //        // 设置所需查询的表格名称为dataset的名称
        //        queryDef.Tables = dataset.Name;
        //        // 设置查询的字段名称。可以联合使用SQL语言的关键字，如查询唯一值可以使用DISTINCT关键字。
        //        queryDef.SubFields = "DISTINCT (" + fieldName + ")";
        //        // 执行查询并返回ICursor接口的对象来访问整个结果的集合
        //        ICursor cursor = queryDef.Evaluate();

        //        // 使用IField接口获取当前所需要使用的字段的信息
        //        IFields fields = pFeatureLayer.FeatureClass.Fields;
        //        IField field = fields.get_Field(fields.FindField(fieldName));

        //        // 对整个结果集合进行遍历，从而添加所有的唯一值
        //        // 使用IRow接口来操作结果集合。首先定位到第一个查询结果。
        //        IRow row = cursor.NextRow();
        //        //如果查询结果非空，则一直进行添加操作
        //        while (row != null)
        //        {
        //            //对String类型的字段，唯一值的前后添加'和'，以符合SQL语句的要求
        //            if (field.Type == esriFieldType.esriFieldTypeString)
        //            {
        //                resultList.Add("\'" + row.get_Value(0).ToString() + "\'");
        //            }
        //            else
        //            {
        //                resultList.Add(row.get_Value(0).ToString());
        //            }
        //            //继续执行下一个结果的添加
        //            row = cursor.NextRow();
        //        }

        //        return resultList;
        //    }
        //    catch (Exception ex)
        //    {
        //        ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, "获取唯一值失败");
        //        return null;
        //    }
        //}

        /// <summary>
        /// 对GeoFeature图层做单一值渲染
        /// </summary>
        /// <param name="pGeoFeatureLayer">对哪个图层渲染</param>
        /// <param name="marker3DSymbolFilePath">3D模型文件路径</param>
        /// <returns>返回是否设置成功</returns>
        public static bool Set3DSymbol_Single(this IGeoFeatureLayer pGeoFeatureLayer, string marker3DSymbolFilePath, string sizeRendererExpression)
        {
            try
            {
                // 设置符号的形状
                IMarker3DSymbol marker3DSymbol = new Marker3DSymbolClass();
                marker3DSymbol.CreateFromFile(marker3DSymbolFilePath);

                (marker3DSymbol as IMarkerSymbol).Size = marker3DSymbol.Shape.Envelope.Depth * 30;
                (marker3DSymbol as IMarkerSymbol).Angle = 0;
                (marker3DSymbol as IMarkerSymbol).XOffset = 0;
                (marker3DSymbol as IMarkerSymbol).YOffset = 0;
                // 设置图层的渲染器
                ISimpleRenderer pSimpleRenderer = new SimpleRendererClass();
                pSimpleRenderer.Symbol = marker3DSymbol as ISymbol;
                #region 设置依据“表达式”来设置符号的大小
                ISizeRenderer pSizeRender = pSimpleRenderer as ISizeRenderer;
                pSizeRender.SizeRendererFlags = (int)(string.IsNullOrWhiteSpace(sizeRendererExpression) ? esriSizeRendererFlags.esriSizeRendererNone : esriSizeRendererFlags.esriSizeRendererUseExpression);
                pSizeRender.SizeRendererExpression = sizeRendererExpression;
                #endregion
                pGeoFeatureLayer.Renderer = pSimpleRenderer as IFeatureRenderer;

                return true;
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("图层“{0}”进行SingleValue渲染失败", pGeoFeatureLayer.Name));
                return false;
            }
        }
        /// <summary>
        /// 对图层进行3D渲染，根据某个字段唯一值渲染并根据另一字段设置样式的大小
        /// <para>@Author: [风过 无痕](https://home.cnblogs.com/u/xiexiaokui/)</para>
        /// <para>@Address: [arcengine 要素渲染和专题图制作](https://www.cnblogs.com/xiexiaokui/archive/2008/08/18/1270124.html)</para>
        /// <para>@Author: [vic](https://www.cnblogs.com/vichang/)</para>
        /// <para>@Address:[【GIS】点图层符号的方向和大小](https://www.cnblogs.com/vichang/p/6826212.html)</para>
        /// </summary>
        /// <param name="pGeoFeatureLayer">调用对象</param>
        /// <param name="uniqueValueField">唯一值渲染的字段</param>
        /// <param name="value_filePath">唯一值渲染中各个唯一值所对应的3D文件路径</param>
        /// <param name="sizeRendererExpression">根据哪个字段设置样式的大小</param>
        /// <returns>是否设置成功</returns>
        public static bool Set3DSymbol_UniqueWithoutSplitLayer(this IGeoFeatureLayer pGeoFeatureLayer, string uniqueValueField, Dictionary<string, string> value_filePath, string sizeRendererExpression)
        {
            IUniqueValueRenderer pUniqueValueRenderer = new UniqueValueRendererClass();

            #region 使用1个字段来渲染，这个字段就是传入的唯一值分类依据
            pUniqueValueRenderer.FieldCount = 1;
            pUniqueValueRenderer.set_Field(0, uniqueValueField);
            #region 设置默认符号【未命名树种】
            pUniqueValueRenderer.DefaultLabel = "未命名树种";
            ISimpleMarkerSymbol pSimpleMarkerSymbol = new SimpleMarkerSymbolClass();
            pSimpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCross;
            IRgbColor pRgbColor = new RgbColorClass();
            pRgbColor.Red = 255;
            pRgbColor.Green = 0;
            pRgbColor.Blue = 0;
            pSimpleMarkerSymbol.Color = pRgbColor;
            pUniqueValueRenderer.DefaultSymbol = pSimpleMarkerSymbol as ISymbol;
            #endregion
            #endregion
            #region 向唯一值Renderer中添加“数据”
            foreach (KeyValuePair<string, string> pair in value_filePath)
            {
                // 设置符号的形状
                IMarker3DSymbol pMarker3DSymbol = new Marker3DSymbolClass();
                pMarker3DSymbol.CreateFromFile(pair.Value);

                IMarkerSymbol pMarkerSymbol = pMarker3DSymbol as IMarkerSymbol;
                pMarkerSymbol.Size = pMarker3DSymbol.Shape.Envelope.Depth;
                pMarkerSymbol.Angle = 0;
                pMarkerSymbol.XOffset = 0;
                pMarkerSymbol.YOffset = 0;

                try
                {
                    // 添加值【还可以通过set_Symbol,set_Heading、set_Value来修改上述设置。】
                    pUniqueValueRenderer.AddValue(pair.Key, null, pMarker3DSymbol as ISymbol);
                }
                catch (Exception ex)
                {
                    ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("图层“{0}”对字段“{1}”进行UniqueValue渲染失败", pGeoFeatureLayer.Name, uniqueValueField));
                    return false;
                }
            }
            #endregion
            #region 设置依据“表达式”来设置符号的大小
            #region 来源信息
            /* @Author: [vic](https://www.cnblogs.com/vichang/);
             * @Address:[【GIS】点图层符号的方向和大小](https://www.cnblogs.com/vichang/p/6826212.html)
             */
            #endregion
            ISizeRenderer pSizeRender = pUniqueValueRenderer as ISizeRenderer;
            pSizeRender.SizeRendererFlags = (int)(string.IsNullOrWhiteSpace(sizeRendererExpression) ? esriSizeRendererFlags.esriSizeRendererNone : esriSizeRendererFlags.esriSizeRendererUseExpression);
            pSizeRender.SizeRendererExpression = sizeRendererExpression;
            #endregion

            pGeoFeatureLayer.Renderer = pUniqueValueRenderer as IFeatureRenderer;
            return true;
        }
        /// <summary>
        /// 更新某个图层中某个唯一值的3D样式
        /// <para>@Tips: 不是字段名而是唯一值！</para>
        /// </summary>
        /// <param name="pGeoFeatureLayer">哪个图层</param>
        /// <param name="uniqueValue">哪个唯一值【不是字段名而是唯一值】</param>
        /// <param name="marker3DSymbolFilePath">3D模型路径</param>
        /// <returns>是否更改成功</returns>
        public static bool Update3DSymbol(this IGeoFeatureLayer pGeoFeatureLayer, string uniqueValue, string marker3DSymbolFilePath)
        {
            #region 声明变量
            IUniqueValueRenderer pUniqueValueRenderer = pGeoFeatureLayer.Renderer as IUniqueValueRenderer;
            IMarker3DSymbol pMarker3DSymbol;
            IMarkerSymbol pMarkerSymbol;
            #endregion
            #region 设置更改的模型
            try
            {
                pMarker3DSymbol = new Marker3DSymbolClass();
                pMarker3DSymbol.CreateFromFile(marker3DSymbolFilePath);

                pMarkerSymbol = pMarker3DSymbol as IMarkerSymbol;
                pMarkerSymbol.Size = pMarker3DSymbol.Shape.Envelope.Depth;
                pMarkerSymbol.Angle = 0;
                pMarkerSymbol.XOffset = 0;
                pMarkerSymbol.YOffset = 0;
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("3D样式模型“{0}”不存在", marker3DSymbolFilePath));
                return false;
            }
            #endregion
            #region 更改模型
            try
            {
                pUniqueValueRenderer.set_Symbol(uniqueValue, pMarkerSymbol as ISymbol);
                return true;
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("图层“{0}”更改值为“{1}”的样式失败", pGeoFeatureLayer.Name, uniqueValue));
                return false;
            }
            #endregion
        }
        /// <summary>
        /// 将GeoFeature图层“浮动”(贴合)在TIN图层上
        /// </summary>
        /// <param name="pGeoFeatureLayer">需要贴合的GeoFeature图层</param>
        /// <param name="pTinLayer">浮动在哪一个Tin图层上</param>
        public static void FloatOnTinLayer(this IGeoFeatureLayer pGeoFeatureLayer, ITinLayer pTinLayer)
        {
            //设置3D属性
            ITinAdvanced tinAdvanced = pTinLayer.Dataset as ITinAdvanced;
            ISurface surface = tinAdvanced.Surface;

            ILayerExtensions layerExtensions = pGeoFeatureLayer as ILayerExtensions;
            I3DProperties p3DProperties = null;

            for (int i = 0; i < layerExtensions.ExtensionCount; i++)
            {
                if (layerExtensions.get_Extension(i) is I3DProperties)
                {
                    p3DProperties = layerExtensions.get_Extension(i) as I3DProperties;
                }
            }
            p3DProperties.BaseOption = esriBaseOption.esriBaseSurface;
            p3DProperties.BaseSurface = surface;
            p3DProperties.Apply3DProperties(pGeoFeatureLayer);
        }

        #region 已废弃
        /// <summary>
        /// 对GeoFeature图层中的某一个字段做唯一值分类【不依据唯一值分割图层】
        /// <para>@Author: [风过 无痕](https://home.cnblogs.com/u/xiexiaokui/)</para>
        /// <para>@Address: [arcengine 要素渲染和专题图制作](https://www.cnblogs.com/xiexiaokui/archive/2008/08/18/1270124.html)</para>
        /// </summary>
        /// <param name="pGeoFeatureLayer">需要渲染的图层</param>
        /// <param name="uniqueValueField">需要渲染的字段</param>
        /// <param name="value_filePath">键值对[唯一值,3D模型文件路径]</param>
        /// <returns>返回是否设置成功</returns>
        private static bool Set3DSymbol_Unique(this IGeoFeatureLayer pGeoFeatureLayer, string uniqueValueField, Dictionary<string, string> value_filePath)
        {
            #region 设置“唯一值”Renderer
            // 构造一个UniqueValueRenderer
            IUniqueValueRenderer renderer = new UniqueValueRendererClass();
            // 使用1个字段来渲染，这个字段就是传入的唯一值分类依据
            renderer.FieldCount = 1;
            renderer.set_Field(0, uniqueValueField);
            // 设置默认符号【未命名树种】
            renderer.DefaultLabel = "未命名树种";
            #endregion

            foreach (KeyValuePair<string, string> pair in value_filePath)
            {
                // 设置符号的形状
                IMarker3DSymbol marker3DSymbol = new Marker3DSymbolClass();
                marker3DSymbol.CreateFromFile(pair.Value);

                (marker3DSymbol as IMarkerSymbol).Size = marker3DSymbol.Shape.Envelope.Depth * 14;
                (marker3DSymbol as IMarkerSymbol).Angle = 0;
                (marker3DSymbol as IMarkerSymbol).XOffset = 0;
                (marker3DSymbol as IMarkerSymbol).YOffset = 0;

                // 添加值【还可以通过set_Symbol,set_Heading、set_Value来修改上述设置。】
                try
                {
                    renderer.AddValue(pair.Key, pair.Key, marker3DSymbol as ISymbol);
                }
                catch (Exception ex)
                {
                    ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("图层“{0}”对字段“{1}”进行UniqueValue渲染失败", pGeoFeatureLayer.Name, uniqueValueField));
                    return false;
                }
            }
            pGeoFeatureLayer.Renderer = renderer as IFeatureRenderer;
            return true;
        }
        /// <summary>
        /// 采用等间隔分类(EqualIntervalClass)中的默认方法进行分级渲染
        /// <para>@Author: [dreamgis](https://blog.csdn.net/dreamgis?type=download)</para>
        /// <para>@Address: [ArcEngine专题图源码(含测试数据)](https://download.csdn.net/download/dreamgis/4497225)</para>
        /// </summary>
        /// <param name="pGeoFeatureLayer">对哪个图层进行分类渲染</param>
        /// <param name="brokenFieldName">对哪个字段进行分类渲染</param>
        /// <returns>返回是否设置成功</returns>
        private static bool SetGraduateSymbol(this IGeoFeatureLayer pGeoFeatureLayer, string brokenFieldName, string marker3DSymbolFilePath, int levelCount = 5)
        {
            #region 变量声明
            // 用于统计的量：“brokenFieldName”字段(需要分类渲染字段)的直方图
            ITable pFeatureClassTable;
            ITableHistogram pTableHistogram;
            // 统计之后的数据
            object dataFrequency;
            object dataValues;
            // 利用统计之后的数据进行自动“打断点”(设置分段点)
            IClassifyGEN pClassify;
            double[] classBreaks;
            int classBreaksCount;
            int numDesiredClasses = levelCount;
            // 分类渲染器
            IClassBreaksRenderer pClassBreakRenderer;
            double symbolSizeOrigin;
            #endregion
            #region 统计FeatureLayer的直方图
            pFeatureClassTable = pGeoFeatureLayer.FeatureClass as ITable;
            pTableHistogram = new BasicTableHistogramClass();
            pTableHistogram.Field = brokenFieldName;
            pTableHistogram.Table = pFeatureClassTable;
            (pTableHistogram as IBasicHistogram).GetHistogram(out dataValues, out dataFrequency);
            #endregion
            #region 下面是分级方法，用于根据获得的值计算得出符合要求的数据
            pClassify = new EqualIntervalClass();
            try
            {
                // 将直方图数据和频率(两个成对的数组)分类为指定数量的类。
                pClassify.Classify(dataValues, dataFrequency, ref numDesiredClasses);
            }
            catch (Exception ex)
            {
                ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("“{0}”图层对“{1}”字段ClassBreak渲染失败", pGeoFeatureLayer.Name, brokenFieldName));
                return false;
            }
            // 根据条件计算出classBreaks和classBreaksCount，5为分级数目[ARCGIS默认值]
            classBreaks = (double[])pClassify.ClassBreaks;
            classBreaksCount = classBreaks.GetUpperBound(0);
            #endregion
            #region 设置分类渲染器
            pClassBreakRenderer = new ClassBreaksRendererClass();
            pClassBreakRenderer.Field = brokenFieldName;
            // 设置着色对象的分级数目
            pClassBreakRenderer.BreakCount = classBreaksCount;
            pClassBreakRenderer.SortClassesAscending = true;
            // 设置样式的起始大小
            if (classBreaksCount <= 5)
            {
                symbolSizeOrigin = 12.0d;
            }
            else if (classBreaksCount < 10 && classBreaksCount > 5)
            {
                symbolSizeOrigin = 7.0d;
            }
            else
            {
                symbolSizeOrigin = 5.0d;
            }
            // 需要注意的是分级着色对象中的symbol和break的下标都是从0开始
            for (int breakCursor = 0; breakCursor < classBreaksCount; breakCursor++)
            {
                pClassBreakRenderer.set_Break(breakCursor, classBreaks[breakCursor + 1]);
                #region 设置3D样式
                IMarker3DSymbol marker3DSymbol = new Marker3DSymbolClass();
                marker3DSymbol.CreateFromFile(marker3DSymbolFilePath);
                (marker3DSymbol as IMarkerSymbol).Size = symbolSizeOrigin + breakCursor * symbolSizeOrigin / 3.0d;
                pClassBreakRenderer.set_Symbol(breakCursor, marker3DSymbol as ISymbol);
                #endregion
            }
            pGeoFeatureLayer.Renderer = (IFeatureRenderer)pClassBreakRenderer;

            return true;
            #endregion
        }
        /// <summary>
        /// 根据某个字段的值设置样式的大小
        /// </summary>
        /// <param name="pGeoFeatureLayer">对哪个图层</param>
        /// <param name="sizeField">对哪个字段</param>
        /// <returns>是否设置成功</returns>
        private static bool SetSizeByAttribute(this IGeoFeatureLayer pGeoFeatureLayer, string sizeField)
        {
            // 遍历IFeature。
            #region 对Recycling的解释
            /* Recycling: Recycling的意思是回收。参数Recycling：
             *      为True的时当执行这个方法IFeature pFeature=pFeatureCursor.NextFeature()上一条记录的值在内存中所占的地址就会被销毁回收
             *      为False时当执行这个方法IFeature pFeature=pFeatureCursor.NextFeature()上一条记录的值依然存在在内存中
             * @Author : [gisoracle](https://www.cnblogs.com/gisoracle/);
             * @Address: [IFeatureClass.Search(IQuery Filter,bool Recycling)参数说明](https://www.cnblogs.com/gisoracle/archive/2012/01/28/2330541.html);
             */
            #endregion
            IFeatureCursor pFeatureCursor = pGeoFeatureLayer.Search(null, true);
            IFeature pFeature = pFeatureCursor.NextFeature();
            while (pFeature != null)
            {
                try
                {
                    int sizeIndex = pFeature.Fields.FindField(sizeField);
                    double size = Double.Parse(pFeature.Value[sizeIndex].ToString());
                    // 没有用？？？？？！！！！！
                    ((IMarkerSymbol)pGeoFeatureLayer.Renderer.SymbolByFeature[pFeature]).Size = size;
                    double recordSize = (pGeoFeatureLayer.Renderer.SymbolByFeature[pFeature] as IMarkerSymbol).Size;
                }
                catch (Exception ex)
                {
                    ExceptionLog.ExceptionLogRecorder.WriteExceptionLog(ex, string.Format("图层“{0}”，依据属性“{1}”设置大小(分类渲染)，失败", pGeoFeatureLayer.Name, sizeField));
                    return false;
                }
                pFeature = pFeatureCursor.NextFeature();
            }
            Marshal.ReleaseComObject(pFeatureCursor);
            return true;
        }
        #endregion
        #region 未确定
        private static bool GraduatedSymbolRenderer(this IGeoFeatureLayer pGeoFeatureLayer, string brokenFieldName, int levelCount)
        {
            ITable pFeatureClassTable;
            IClassifyGEN pClassify;
            ITableHistogram pTableHistogram;
            IBasicHistogram pHistogram;
            object dataFrequency;
            object dataValues;
            double[] classBreaks;
            int classBreaksCount;
            IClassBreaksRenderer pClassBreakRenderer;
            ISimpleMarkerSymbol pCharacterMarkerS = new SimpleMarkerSymbolClass();
            int IbreakIndex;
            string strPopField = brokenFieldName;
            int numDesiredClasses = levelCount;

            //获得要着色的图层
            pFeatureClassTable = (ITable)pGeoFeatureLayer.FeatureClass;
            //从pTable的“GDP_2000（”字段中得到信息给datavalues和datafrequency两个数组
            pTableHistogram = new BasicTableHistogramClass();
            pHistogram = (IBasicHistogram)pTableHistogram;
            pTableHistogram.Field = strPopField;
            pTableHistogram.Table = pFeatureClassTable;
            pHistogram.GetHistogram(out dataValues, out dataFrequency);
            //下面是分级方法，用于根据获得的值计算得出符合要求的数据
            //根据条件计算出Classes和ClassCount，5为分级数目(分类为等间隔类)
            pClassify = new EqualIntervalClass();
            try
            {
                // 将直方图数据和频率(两个成对的数组)分类为指定数量的类。
                pClassify.Classify(dataValues, dataFrequency, ref numDesiredClasses);
            }
            catch (Exception ex)
            {
                return false;
            }
            //返回一个数组
            classBreaks = (double[])pClassify.ClassBreaks;
            classBreaksCount = classBreaks.GetUpperBound(0);
            pClassBreakRenderer = new ClassBreaksRendererClass();
            pClassBreakRenderer.Field = strPopField;
            //设置着色对象的分级数目
            pClassBreakRenderer.BreakCount = classBreaksCount;
            pClassBreakRenderer.SortClassesAscending = true;
            //需要注意的是分级着色对象中的symbol和break的下标都是从0开始
            double symbolSizeOrigin = 5.0;
            if (classBreaksCount <= 5) symbolSizeOrigin = 12;
            if (classBreaksCount < 10 && classBreaksCount > 5) symbolSizeOrigin = 7;
            for (IbreakIndex = 0; IbreakIndex <= classBreaksCount - 1; IbreakIndex++)
            {
                //pColor = pEnumColors.Next();
                //pSimpleFillS = new SimpleFillSymbolClass();
                //pSimpleFillS.Color = pColor;
                //pSimpleFillS.Style = esriSimpleFillStyle.esriSFSSolid;
                //pClassBreakRenderer.set_Symbol(IbreakIndex, (ISymbol)pSimpleFillS);               
                pClassBreakRenderer.set_Break(IbreakIndex, classBreaks[IbreakIndex + 1]);
                pCharacterMarkerS = new SimpleMarkerSymbolClass();
                pCharacterMarkerS.Color = GetRGBColor(0, 255, 0);
                pCharacterMarkerS.Size = symbolSizeOrigin + IbreakIndex * symbolSizeOrigin / 3.0d;
                pClassBreakRenderer.set_Symbol(IbreakIndex, (ISymbol)pCharacterMarkerS);
            }
            pGeoFeatureLayer.Renderer = (IFeatureRenderer)pClassBreakRenderer;

            return true;
        }
        private static IColor GetRGBColor(int red, int green, int blue)
        {
            IRgbColor RgbClr = new RgbColorClass();
            RgbClr.Red = red;
            RgbClr.Green = green;
            RgbClr.Blue = blue;
            return RgbClr;
        }
        private static void UniqueValueRenderer(IFeatureLayer pFeatureLayer, string fieldName)
        {
            IGeoFeatureLayer pGeoFeatureLayer = pFeatureLayer as IGeoFeatureLayer;
            ITable pTable = pFeatureLayer as ITable;
            int fieldNumber = pTable.FindField(fieldName);
            IUniqueValueRenderer pUniqueRenderer = new UniqueValueRendererClass();
            pUniqueRenderer.FieldCount = 1;
            pUniqueRenderer.set_Field(0, fieldName);

            //设置显示颜色的范围
            IRandomColorRamp pRandColorRamp = new RandomColorRampClass();
            pRandColorRamp.StartHue = 0;
            pRandColorRamp.MinValue = 85;
            pRandColorRamp.MinSaturation = 15;
            pRandColorRamp.EndHue = 360;
            pRandColorRamp.MaxValue = 100;
            pRandColorRamp.MaxSaturation = 30;

            //创建随机颜色带
            bool bSucess = false;
            pRandColorRamp.CreateRamp(out bSucess);

            IEnumColors pEnumColors = pRandColorRamp.Colors;
            IColor pNextUniqueColor = null;

            //属性唯一值
            IQueryFilter pQueryFilter = new QueryFilterClass();
            pQueryFilter.AddField(fieldName);
            ICursor pCursor = pFeatureLayer.FeatureClass.Search(pQueryFilter, false) as ICursor;
            IRow pNextRow = pCursor.NextRow();
            object codeValue = null;
            IRowBuffer pNextRowBuffer = null;

            IFillSymbol pFillSymbol = null;
            ILineSymbol pLineSymbol = null;
            IMarkerSymbol pMarkerSymbol = null;
            while (pNextRow != null)
            {
                pNextRowBuffer = pNextRow as IRowBuffer;
                codeValue = pNextRowBuffer.get_Value(fieldNumber);
                pNextUniqueColor = pEnumColors.Next();
                if (pNextUniqueColor == null)
                {
                    pEnumColors.Reset();
                    pNextUniqueColor = pEnumColors.Next();
                }
                switch (pGeoFeatureLayer.FeatureClass.ShapeType)
                {
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint:
                        pMarkerSymbol = new SimpleMarkerSymbolClass();
                        pMarkerSymbol.Color = pNextUniqueColor;
                        pUniqueRenderer.AddValue(codeValue.ToString(), "", pMarkerSymbol as ISymbol);
                        pNextRow = pCursor.NextRow();
                        break;
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
                        pLineSymbol = new SimpleLineSymbolClass();
                        pLineSymbol.Color = pNextUniqueColor;
                        pUniqueRenderer.AddValue(codeValue.ToString(), "", pLineSymbol as ISymbol);
                        pNextRow = pCursor.NextRow();
                        break;
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:
                        pFillSymbol = new SimpleFillSymbolClass();
                        pFillSymbol.Color = pNextUniqueColor;
                        pUniqueRenderer.AddValue(codeValue.ToString(), "", pFillSymbol as ISymbol);
                        pNextRow = pCursor.NextRow();
                        int k = pFillSymbol.Color.CMYK;
                        break;
                    default:
                        break;
                }
            }
            pGeoFeatureLayer.Renderer = pUniqueRenderer as IFeatureRenderer;

            //必须手动清除COM对象，否则会造成内存溢出（尤其是IQueryFilter,ICursor）
            Marshal.ReleaseComObject(pQueryFilter);
            Marshal.ReleaseComObject(pCursor);
            Marshal.ReleaseComObject(pEnumColors);
        }
        #endregion
    }
}
